<template>
    <div id="app">
        <transition :name="pageTransitionEffect" @before-enter="handleBeforeEnter" @after-enter="handleAfterEnter" @before-leave="handleBeforeLeave">
            <router-view :key="routerViewKey" :class="['app-view', pageTransitionClass]" :data-page-id="$route.fullPath">
            </router-view>
        </transition>
        <update-toast></update-toast>
    </div>
</template>

<script>
import Vue from 'vue';
import { mapState, mapActions, mapMutations } from 'vuex';
import UpdateToast from '@/components/UpdateToast';
import { keepAlivePages } from '@/.lavas/router';

const ENABLE_SCROLL_CLASS = 'app-view-scroll-enabled';

export default {
    name: 'app',
    components: {
        UpdateToast
    },
    computed: {
        ...mapState('pageTransition', {
            pageTransitionType: state => state.type,
            pageTransitionEffect: state => state.effect
        }),

        ...mapState('scrollBehavior', {
            scrollPostionMap: state => state.scrollPostionMap
        }),

        ...mapState('chatStatus', {
            logged: state => state.logged,
            members: state => state.members
        }),

        pageTransitionClass() {
            return `transition-${this.pageTransitionType}`;
        },

        // https://github.com/lavas-project/lavas/issues/119
        routerViewKey() {
            let { name, params } = this.$route;
            let paramKeys = Object.keys(params);
            if (paramKeys.length) {
                return name + paramKeys.reduce((prev, cur) => prev + params[cur], '');
            }
            return null;
        }
    },
    data() {
        return {
            // https://github.com/lavas-project/lavas/issues/112
            keepAlivePages
        };
    },
    mounted() {
        
    },
    methods: {
        ...mapActions('scrollBehavior', [
            'savePageScrollPosition'
        ]),

        ...mapMutations('chatStatus', [
            'setLog',
            'setMembers'
        ]),

        /**
         * make current page container scrollable,
         * and restore its scroll position.
         */
        restoreContainerScrollPosition(containerEl, scrollTop) {
            containerEl.classList.add(ENABLE_SCROLL_CLASS);
            containerEl.scrollTop = scrollTop;
        },

        /**
         * make body scrollable,
         * and restore its scroll position.
         */
        restoreBodyScrollPosition(containerEl, scrollTop) {
            containerEl.classList.remove(ENABLE_SCROLL_CLASS);
            document.body.scrollTop = document.documentElement.scrollTop = scrollTop;
        },

        handleBeforeEnter(el) {
            let pageId = el.dataset.pageId;
            let { y: scrollTop = 0 } = this.scrollPostionMap[pageId] || {};
            Vue.nextTick(() => {
                this.restoreContainerScrollPosition(el, scrollTop);
            });
        },

        handleAfterEnter(el) {
            let pageId = el.dataset.pageId;
            let { y: scrollTop = 0 } = this.scrollPostionMap[pageId] || {};
            this.restoreBodyScrollPosition(el, scrollTop);
        },

        handleBeforeLeave(el) {
            let pageId = el.dataset.pageId;
            let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
            this.restoreContainerScrollPosition(el, scrollTop);
            // save current scroll position in a map
            this.savePageScrollPosition({
                pageId,
                scrollPosition: { y: scrollTop }
            });
        }
    }
};
</script>

<style>
#app {
	width: 100%;
	height: 100%;
}
</style>
